package com.hyl.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * LoggerAscpect
 *
 * @author hyl
 * @date 2025-06-23
 */
@Component
@Aspect
public class LoggerAscpectAnnotation {
    // 日志记录对象
    private static final Logger log = LoggerFactory.getLogger(LoggerAscpectAnnotation.class);
    /**
     * 前置增强-打印进入方法和参数
     */
    @Before("execution(* com.hyl.service.*.*(..))")
    public void before(JoinPoint jp) {
        log.info("【LoggerAspect 前置增强】正在调用 {} 的{}方法。方法入参：{}",
                jp.getTarget(), jp.getSignature().getName(),
                Arrays.toString(jp.getArgs()));
    }
    /**
     * 后置增强-打印返回结果
     */
    @AfterReturning(value = "execution(* com.hyl.service.*.*(..))",
            returning = "result")
    public void afterReturning(JoinPoint jp, Object result) {
        log.info("【LoggerAspect 后置增强】调用 {} 的 {}方法。方法返回值：{}",
                jp.getTarget(), jp.getSignature().getName(), result);
    }


    /**
     * 异常抛出增强-执行事务回滚
     */
    @AfterThrowing(value = "execution(* com.hyl.service.*.*(..))",
            throwing = "e")
    public void afterThrowing(JoinPoint jp, Throwable e){
        log.info("【LoggerAspect 异常抛出增强】异常信息为："
                + e.getMessage());
    }
    /**
     * 最终增强-执行关闭数据库资源
     */
    @After("execution(* com.hyl.service.*.*(..))")
    public void after(JoinPoint jp){
        log.info("【LoggerAspect 最终增强】释放资源...");
    }

    /**
     * 环绕增强
     */
    public Object around(ProceedingJoinPoint jp) throws Throwable {
        log.info("【环绕增强-前置】记录{}方法执行的开始时间.",
                jp.getSignature().getName());
        // 进入方法之前就记录开始时间
        long startTime = System.currentTimeMillis();
        try {
            // 通过proceed()方法可以执行目标方法
            Object result = jp.proceed();
            log.info("【环绕增强-后置】{}方法执行结果为{}." ,
                    jp.getSignature().getName() , result);
            // 注意：环绕增强要将结果返回
            return result;
        } catch (Throwable e) {
            log.info("【环绕增强-异常抛出】{}方法执行异常信息为{}." ,
                    jp.getSignature().getName() , e.getMessage());
            // 注意：不能隐瞒异常，需要抛出
            throw e;
        } finally {
            // 在finally中记录结束时间，保证不管正常还是异常都能记录执行时间
            long endTime = System.currentTimeMillis();
            log.info("【环绕增强-最终】记录{}方法执行的结束时间，并计算耗时为{}ms.",
                    jp.getSignature().getName() , (endTime - startTime));
        }
    }
}
